#include "../include/thread_pool.h"
#include "../include/config.h"

#define EPOLL_ARR_SIZE 100

int exitPipe[2];
void sighandle(int signum){
    printf("\n sigunm = %d\n",signum);
    printf("\n sig is coming.\n");
    int one = 1;
    write(exitPipe[1],&one,sizeof(one));
}

int main(int argc,char *argv[]){
    ARGS_CHECK(argc,2);
    // 创建匿名管道
    pipe(exitPipe);

    // fork()之后，将创建了子进程
    pid_t pid =fork();
    if(pid > 0){
        close(exitPipe[0]);// 父进程关闭读端
        signal(SIGUSR1,sighandle);
        wait(NULL); // 等待子进程退出，回收其资源
        close(exitPipe[1]);
        printf("/nparent process exit.\n");
        exit(0); // 父进程退出
    }

    // 以下都是子进程中的执行流程
    close(exitPipe[1]); // 子进程关闭写端
    
    // 初始化hash表，用来存储配置信息
    HashTable ht;
    initHashTable(&ht);
    // 读取服务器配置文件
    readConfig(argv[1],&ht);

    // 创建线程池结构体
    threadpool_t threadpool;
    bzero(&threadpool,sizeof(threadpool_t));
    
    // 初始化线程池
    threadpoolInit(&threadpool,atoi((const char *)find(&ht,THREAD_NUM)));
    // 启动线程池
    threadpoolStart(&threadpool);

    // 创建监听套接字
    int sockfd = tcpInit((const char *)find(&ht,IP), (const char *)find(&ht,PORT));

    // 创建epoll实例
    int epfd = epoll_create(1);
    ERROR_CHECK(epfd,-1,"epoll_create");

    // 对sockfd进行监听
    addEpollReadfd(epfd,sockfd);
    addEpollReadfd(epfd,exitPipe[0]);

    struct epoll_event *pEventArr = (struct epoll_event *)calloc(EPOLL_ARR_SIZE,sizeof(struct epoll_event));

    while(1){
        int nready = epoll_wait(epfd,pEventArr,EPOLL_ARR_SIZE,-1);
        if(nready == -1 && errno == EINTR){
            continue;
        }else if (nready == -1){
            ERROR_CHECK(nready,-1,"epoll_wait");
        }else{
            for(int i = 0; i < nready; ++i){
                int fd = pEventArr[i].data.fd;
                if(fd == sockfd){ // 对新连接进行处理
                    int peerfd = accept(sockfd,NULL,NULL);
                    printf("\nconn %d has connected \n",peerfd);

                    // 将新连接添加到epoll的监听红黑树上
                    addEpollReadfd(epfd,peerfd);
                }else if(fd == exitPipe[0]){
                    // 线程池要退出
                    int howmany = 0;
                    // 对管道进行处理
                    read(exitPipe[0],&howmany,sizeof(howmany));
                    // 主线程通知所有的子线程退出
                    threadpoolStop(&threadpool);
                    // 子进程退出前，回收资源
                    threadpoolDestroy(&threadpool);
                    close(sockfd);
                    close(epfd);
                    close(exitPipe[0]);

                    destroyHashTable(&ht);
                    exit(0);
                }else{ // 客服端连接处理
                    int readConfig(const char *filename, HashTable *ht);
                }
            }
        }
    }
    return 0;
}
